package zrpc

import (
    "context"
    "fmt"
    "net"
    "net/rpc"
    "sync"

    "gitee.com/shijingzhao/z-frame/zlog"
)

// NewServer 实例rpc服务器
func NewServer(ctx context.Context, config Config) *Server {
    addr, err := net.ResolveTCPAddr("tcp", config.Addr)
    if err != nil {
        panic(any(fmt.Sprintf("rpc服务端:启动失败[%s]", err.Error())))
    }

    lis, err := net.ListenTCP("tcp", addr)
    if err != nil {
        panic(any(fmt.Sprintf("rpc服务端:监听异常[%s]", err.Error())))
    }

    return &Server{
        ctx:      ctx,
        ser:      rpc.NewServer(),
        lis:      lis,
        config:   config,
        Handlers: make([]Handler, 0),
    }
}

// AddHandler 添加rpc
func (s *Server) AddHandler(handlers []Handler) {
    s.Handlers = append(s.Handlers, handlers...)
}

// Start 启动
func (s *Server) Start(wg *sync.WaitGroup) {
    for _, handler := range s.Handlers {
        if err := s.ser.Register(handler.Obj); err != nil {
            panic(any(fmt.Sprintf("rpc服务端:注册RPC服务失败[%s]", err.Error())))
        }
    }

    wg.Add(1)
    go func() {
        defer wg.Done()

        for {
            conn, err := s.lis.Accept()
            if err != nil {
                if err.(*net.OpError).Err == net.ErrClosed {
                    zlog.NewSystemLogger(context.TODO()).System("rpc服务器终止")
                    return
                }
                zlog.NewSystemLogger(s.ctx).Error(
                    "rpc服务器:终止错误",
                    zlog.String("s.lis.Accept.err", err.Error()),
                )
                continue
            }
            go s.ser.ServeConn(conn)
        }
    }()
}
